﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Text;
using System.Threading;
using System.Xml.Serialization;

namespace Powershell_ML
{
    public class Server : Exchange_Information
    {

        static PSObject Get_Server = Collectorsvc.Program.Runner.Execute_Command_Once(Const.Get_ExchangeServer);
        public Server() : this(Get_Server, true)
        {

        }
        public List<Server> Get_Organization_Server(int Size, out List<Server> data)
        {
            try
            {
                data = new List<Server>();
                Command Get_ExchangeServerr = new Command("Get-ExchangeServer");
                List<PSObject> Powershell_Output = Collectorsvc.Program.Runner.Execute_Command(Get_ExchangeServerr);
                foreach (PSObject data_entry in Powershell_Output)
                {
                    data.Add(new Server(data_entry, false));
                }
                return data;
            }
            catch { data = null; }
            return null;
        }
        ~Server()
        {
            Console.WriteLine("~Disposing : "
            + this.Name
            + Environment.NewLine
            );
            GC.SuppressFinalize(this);
        }
        public void Dispose()
        {
            Console.WriteLine("Disposing : "
            + this.Name
            + Environment.NewLine
            );
            GC.SuppressFinalize(this);
        }
        public Server(PSObject Obj, bool DynamicObject)
        {
            if (Obj != null)
            {
                Powershell_ML.Famework.IEntry entry = Const.entry;
                this.Property = new List<PSPropertyInfo>();
                this.Property = entry.Property_Creator(Obj);
                this.Collected_Value = Property_Collection(Obj);
                this.Name = this.Extract_String_Property(this.Property, "Name");
                this.Dynamic_Object_Loader = false;
                this.MDB = new List<MailboxDatabase>();
                this.Mailbox = Boolean.Parse(this.Extract_String_Property(this.Property, "IsMailboxServer"));
                this.Transport = Boolean.Parse(this.Extract_String_Property(this.Property, "IsHubTransportServer"));
                this.IsClientAccess = Boolean.Parse(this.Extract_String_Property(this.Property, "IsClientAccessServer"));
                this.ServerRole = this.Extract_String_Property(this.Property, "ServerRole");
                this.Installation_Date = this.Extract_String_Property(this.Property, "WhenCreatedUTC");
                this.Installation_Path = this.Extract_String_Property(this.Property, "DataPath");
                this.FQDN = this.Extract_String_Property(this.Property, "Fqdn");
                this.Edition = this.Extract_String_Property(this.Property, "Edition");
                this.Version = Exchange_Version(Obj);
                this.Domain = this.Extract_String_Property(this.Property, "Domain");
                this.Queue = new List<Powershell_ML.Queue>();
                this.Tracking_Stats = new List<Tracking>();
                this.Site = Get_Adsite(this,this.Extract_String_Property(this.Property, "Site"));
                if(IsClientAccess)
                {
                    System.Threading.Thread Owa = new System.Threading.Thread
                    (delegate ()
                    {
                        this.Owa = Get_Owa_Vdir_ByServer(this.FQDN);
                    });
                    Owa.Start();
                    Owa.Join();

                }
                if(Transport)
                {
                    System.Threading.Thread Queue = new System.Threading.Thread
                    (delegate ()
                    {
                        this.Queue = new List<Powershell_ML.Queue>();
                        this.Queue = Get_Queue(this);
                    });
                    System.Threading.Thread Track = new System.Threading.Thread
                    (delegate ()
                    {
                        this.Tracking_Stats = new List<Tracking>();
                        this.Tracking_Stats = Get_Tracking(this);
                    });
                    Queue.Start();
                    Queue.Join();
                    Track.Start();
                    Track.Join();
                }
                object Property_Info = entry.Get_MultiValuedProperty(Obj, "NetworkAddress");
                this.NetworkAdresses = entry.Icollection_To_List(Property_Info);
                Test_Outlook_Connectivity();
                if (!entry.String_Validation(this.MessageTracking_Path))
                {
                    string datatest = this.MessageTracking_Path.ToString().Replace(":", "$");
                    datatest = datatest.Insert(0, "\\" + this.Name + "\\");
                }
            }
        }
        public Owa_VirtualDirectory Owa
        {
            get;set;
        }
        public bool IsClientAccess
        {
            get;set;
        }
        public string FQDN
        {
            get;set;
        }
        public Ad_Site Site
        {
            get;set;
        }
        public Version Version
        {
            get;set;
        }
        public List<Tracking> Tracking_Stats
        {
            get;set;
        }
        public List<Queue> Queue
        {
            get;
            set;
        }

        public bool Transport
        { get; set;  }
        public List<string> NetworkAdresses
        {
            get; set;
        }
        public string Test_Outlook_Connectivity()
        {
            try
            {
                System.Threading.Thread Powershell_Commands = new System.Threading.Thread
                (delegate ()
                {
                    ManualResetEvent syncEvent = new ManualResetEvent(false);
                    if (Boolean.Parse(this.Extract_String_Property(this.Property, "IsHubTransportServer")))
                    {
                        Command GetMailbox = new Command("Get-TransportServer");
                        GetMailbox.Parameters.Add("-Identity", this.Name);
                        PSObject Entrys = Collectorsvc.Program.Runner.Execute_Command_Once(GetMailbox);
                        this.MessageTracking_Path = Entrys.Properties["MessageTrackingLogPath"].Value.ToString();
                    }
                });
                Powershell_Commands.Start();
                Powershell_Commands.Join();
            }
            catch { }
            return "";
        }
        public string Current_DC
        {
            get; set;
        }
        public string XMLIZED_Object
        {
            get; set;
        }
        public string MessageTracking_Path
        {
            get; set;
        }
        public bool Dynamic_Object_Loader
        {
            get; set;
        }
        public bool Mailbox { get; set; }
        public string Domain
        {
            get; set;

        }
        public string Edition
        {
            get;
            set;
        }
        public string ServerRole
        {
            get;
            set;
        }
        public string Installation_Date
        {
            get;
            set;
        }
        public string Name
        {
            get;
            set;
        }
        public string Installation_Path
        {
            get;
            set;
        }
        [XmlIgnore]
        public Dictionary<string, string> Wanted
        {
            get;
            set;
        }
        [XmlIgnore]
        public List<ICollection> Collected_Value
        {
            get;
            set;
        }
        [XmlIgnoreAttribute]
        public List<PSPropertyInfo> Property
        {
            get;
            set;
        }
        [XmlIgnore]
        public List<MailboxDatabase> MDB
        {
            get; set;
        }
    }

    public class Queue : Exchange_Information
    {
        public Queue()
        {

        }
        public Queue(PSObject Object)
        {
            Powershell_ML.Famework.IEntry entry = Const.entry;
            this.Property = new List<PSPropertyInfo>();
            this.Property = entry.Property_Creator(Object);
            this.Identity = this.Extract_String_Property(this.Property, "Identity");
            this.DeliveryType = this.Extract_String_Property(this.Property, "DeliveryType");
            this.IsValid = this.Extract_String_Property(this.Property, "IsValid");
            this.LastError = this.Extract_String_Property(this.Property, "LastError");
            this.MessageCount = this.Extract_String_Property(this.Property, "MessageCount");
            if (int.Parse(this.MessageCount) > 0)
            {
                this.Messages = new List<Message>();
                Command Get_Queue = new Command("Get-Message");
                Get_Queue.Parameters.Add("Queue", this.Identity);
                List<PSObject> Powershell_Output = Collectorsvc.Program.Runner.Execute_Command(Get_Queue);
                if (Powershell_Output.Count > 0)
                {
                    foreach (PSObject msg in Powershell_Output)
                    {
                        this.Messages.Add(new Message(msg));
                    }
                    string[] Collumn = { "Subject", "InternetMessageId", "FromAddress", "Status", "MessageSourceName", "SourceIP", "SCL", "DateReceived", "ExpirationTime", "LastError", "RetryCount", "Recipients", "ComponentLatency", "DeferReason", "Priority", "Size" };
                    this.Messages_Report = Extend.Build_Table_By_List(this.Messages, Collumn);
                }
            }
            this.NextHopDomain = this.Extract_String_Property(this.Property, "NextHopDomain");
            this.NextHopConnector = this.Extract_String_Property(this.Property, "NextHopConnector");
            this.QueueIdentity = this.Extract_String_Property(this.Property, "QueueIdentity");
            this.status = this.Extract_String_Property(this.Property, "Status");
            this.tlsdomain = this.Extract_String_Property(this.Property, "TlsDomain");
            this.LastError = this.Extract_String_Property(this.Property, "Lasterror");
            this.LastRetryTime = this.Extract_String_Property(this.Property, "LastRetryTime");
            string[] Queue_Request = { "Identity", "DeliveryType", "IsValid", "LastError", "LastRetryTime", "MessageCount", "NextHopConnector", "NextHopDomain", "QueueIdentity", "Status", "TlsDomain" };
            this.Wanted = entry.Wanted_Property_Extractor(Object, Queue_Request);
            string shortname = this.Identity.Substring(this.Identity.IndexOf(@"\") + 1);
            string servername = this.Identity.Substring(0, this.Identity.LastIndexOf(@"\"));
            this.server = servername;
            this.short_queue_name = shortname;
        }
        public string server
        {
            get;set;
        }
        public string short_queue_name
        {
            get;set;
        }
        public string Messages_Report
        {
            get;set;
        }
        public List<Message> Messages
        {
            get;set;
        }
        [XmlIgnoreAttribute]
        public List<PSPropertyInfo> Property
        {
            get;
            set;
        }
        public string tlsdomain { get; set; }
        public string status { get; set; }
        public string QueueIdentity { get; set; }
        public string NextHopDomain { get; set; }
        public string NextHopConnector { get; set; }
        public string MessageCount { get; set; }
        public string LastRetryTime { get; set; }
        public string LastError { get; set; }
        public string IsValid { get; set; }
        public string DeliveryType { get; set; }
        public string Identity { get; set; }
        [XmlIgnoreAttribute]
        public Dictionary<string, string> Wanted
        {
            get;
            set;
        }
    }

    public class Message : Exchange_Information
    {
        public Message()
        {

        }
        public Message(PSObject Object)
        {
            Powershell_ML.Famework.IEntry entry = Const.entry;
            this.Property = new List<PSPropertyInfo>();
            this.Property = entry.Property_Creator(Object);
            this.Subject = this.Extract_String_Property(this.Property, "Subject");
            this.InternetMessageId = this.Extract_String_Property(this.Property, "InternetMessageId");
            this.FromAddress = this.Extract_String_Property(this.Property, "FromAddress");
            this.Status = this.Extract_String_Property(this.Property, "Status");
            this.MessageSourceName = this.Extract_String_Property(this.Property, "MessageSourceName");
            this.SourceIP = this.Extract_String_Property(this.Property, "SourceIP");
            this.SCL = this.Extract_String_Property(this.Property, "SCL");
            this.DateReceived = this.Extract_String_Property(this.Property, "DateReceived");
            this.ExpirationTime = this.Extract_String_Property(this.Property, "ExpirationTime");
            this.LastError = this.Extract_String_Property(this.Property, "LastError");
            this.RetryCount = this.Extract_String_Property(this.Property, "RetryCount");
            this.Recipients = this.Extract_String_Property(this.Property, "Recipients");
            this.ComponentLatency = this.Extract_String_Property(this.Property, "ComponentLatency");
            this.DeferReason = this.Extract_String_Property(this.Property, "DeferReason");
            this.Priority = this.Extract_String_Property(this.Property, "Priority");
            this.Size = this.Extract_String_Property(this.Property, "Size");
        }
        [XmlIgnoreAttribute]
        public List<PSPropertyInfo> Property
        {
            get;
            set;
        }
        public string Size { get; set; }
        public string Priority { get; set; }
        public string DeferReason { get; set; }
        public string MessageLatency { get; set; }
        public string ComponentLatency { get; set; }
        public string Recipients { get; set; }
        public string RetryCount { get; set; }
        public string LastError { get; set; }
        public string ExpirationTime { get; set; }
        public string DateReceived { get; set; }
        public string SCL { get; set; }
        public string SourceIP { get; set; }
        public string MessageSourceName { get; set; }
        public string Status { get; set; }
        public string FromAddress { get; set; }
        public string InternetMessageId { get; set; }
        public string Subject { get; set; }
        [XmlIgnoreAttribute]
        public Dictionary<string, string> Wanted
        {
            get;
            set;
        }
    }

    public class Tracking : Exchange_Information
    {
        public Tracking(PSObject Object)
        {
            Powershell_ML.Famework.IEntry entry = Const.entry;
            this.Property = new List<PSPropertyInfo>();
            this.Property = entry.Property_Creator(Object);
            this.TotalBytes = this.Extract_String_Property(this.Property, "TotalBytes");
            this.Timestamp = this.Extract_String_Property(this.Property, "Timestamp");
            this.SourceContext = this.Extract_String_Property(this.Property, "SourceContext");
            this.Source = this.Extract_String_Property(this.Property, "Source");
            this.ServerIp = this.Extract_String_Property(this.Property, "ServerIp");
            this.Sender = this.Extract_String_Property(this.Property, "Sender");
            this.ReturnPath = this.Extract_String_Property(this.Property, "ReturnPath");
            this.RelatedRecipientAddress = this.Extract_String_Property(this.Property, "RelatedRecipientAddress");
            this.Reference = this.Extract_String_Property(this.Property, "Reference");
            this.RecipientStatus = this.Extract_String_Property(this.Property, "RecipientStatus");
            this.RecipientCount = this.Extract_String_Property(this.Property, "RecipientCount");
            this.MessageSubject = this.Extract_String_Property(this.Property, "MessageSubject");
            this.MessageLatencyType = this.Extract_String_Property(this.Property, "MessageLatencyType");
            this.MessageLatency = this.Extract_String_Property(this.Property, "MessageLatency");
            this.MessageInfo = this.Extract_String_Property(this.Property, "MessageInfo");
            this.MessageId = this.Extract_String_Property(this.Property, "MessageId");
            this.InternalMessageId = this.Extract_String_Property(this.Property, "InternalMessageId");
            this.EventId = this.Extract_String_Property(this.Property, "EventId");
            this.EventData = this.Extract_String_Property(this.Property, "EventData");
            this.ConnectorId = this.Extract_String_Property(this.Property, "ConnectorId");
            this.ClientIp = this.Extract_String_Property(this.Property, "ClientIp");
            this.PSComputerName = this.Extract_String_Property(this.Property, "PSComputerName");
            this.ClientHostname = this.Extract_String_Property(this.Property, "ClientHostname");
            object Property_Info = entry.Get_MultiValuedProperty(Object, "Recipients");
            this.Recipients = entry.Icollection_To_List(Property_Info);
        }
        public List<PSPropertyInfo> Property
        {
            get;
            set;
        }
        public string TotalBytes { get; set; }
        public string Timestamp { get; set; }
        public string SourceContext { get; set; }
        public string Source { get; set; }
        public string ServerIp { get; set; }
        public string Sender { get; set; }
        public string ReturnPath { get; set; }
        public string RelatedRecipientAddress { get; set; }
        public string Reference { get; set; }
        public string RecipientStatus { get; set; }
        public List<string> Recipients { get; set; }
        public string RecipientCount { get; set; }
        public string MessageSubject { get; set; }
        public string MessageLatencyType { get; set; }
        public string MessageLatency { get; set; }
        public string MessageInfo { get; set; }
        public string MessageId { get; set; }
        public string InternalMessageId { get; set; }
        public string EventId { get; set; }
        public string EventData { get; set; }
        public string ConnectorId { get; set; }
        public string ClientIp { get; set; }
        public string PSComputerName { get; set; }
        public string ClientHostname { get; set; }
        public Dictionary<string, string> Wanted
        {
            get;
            set;
        }
    }
}
